package com.aspire.boc.mms.gwcmp.action;

import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import com.aspire.boc.mms.gwcmp.dao.GwcmpKeywordMapper;
import com.aspire.boc.mms.gwcmp.dao.GwcmpProcessTaskMapper;
import com.aspire.boc.mms.gwcmp.dao.GwcmpTableUpdateInfoMapper;
import com.aspire.boc.mms.gwcmp.model.GwcmpKeyword;
import com.aspire.boc.mms.gwcmp.model.GwcmpKeywordExample;
import com.aspire.boc.mms.gwcmp.model.GwcmpProcessTask;
import com.aspire.boc.mms.gwcmp.model.GwcmpProcessTaskExample;
import com.aspire.boc.mms.gwcmp.model.GwcmpTableUpdateInfo;
import com.aspire.boc.mms.gwcmp.model.GwcmpTableUpdateInfoExample;
import com.aspire.boc.mms.gwcmp.util.Constants;
import com.aspire.boc.mms.gwcmp.util.GwcmpAdminUtil;
import com.aspire.boc.mms.wmf.util.Json;
import com.aspire.boc.mms.wmf.util.Page;
import com.aspire.boc.mms.wmf.util.ResourceManager;
/**
 * 关键字Action
 *
 * @date 2016年1月15日 下午3:51:42 
 * @author 朱广祝
 *
 */
@Controller
public class KeywordAct {

    private static Log logger = LogFactory.getLog(KeywordAct.class);
    
    @Autowired
    private GwcmpKeywordMapper gwcmpKeywordMapper;
    
    @Autowired
    private GwcmpProcessTaskMapper gwcmpProcessTaskMapper;
    
    @Autowired
    private GwcmpTableUpdateInfoMapper gwcmpTableUpdateInfoMapper;
    
    ResourceManager resourceManager = ResourceManager.getInstance();

    /**
     * 获取关键字列表
     * @param keyWord
     * @return
     */
    @RequestMapping(value="/keyword/getKeywordList")
    @ResponseBody
    public Map<String, Object> getKeywordList(
			@RequestParam(value = "start", required = true) Integer start,
            @RequestParam(value = "limit", required = true) Integer limit,
			@RequestParam(value = "keyword", required = false) String keyword,
            HttpServletRequest request, HttpServletResponse response) {
        
        // 返回结果
        Map<String, Object> result = new HashMap<String, Object>();
        String operator = GwcmpAdminUtil.getLoginUserName(request);
        StringBuffer logInfo = new StringBuffer();
		logInfo.append("KeywordAct >>>>>").append(" operator:").append(operator)
			.append(" url: /keyword/getKeywordList.do").append(" params: [")
			.append("keyWord=").append(keyword).append("] ");    
		logger.info(logInfo.toString());
		List<GwcmpKeyword> list = null;
		Integer total = 0;
        try {
        	GwcmpKeywordExample example = new GwcmpKeywordExample();
        	example.setOrderByClause("LATEST_OPERATE_TIME DESC");
        	GwcmpKeywordExample.Criteria criteria = example.createCriteria();
        	if (StringUtils.isNotBlank(keyword)) {
                criteria.andKeywordLike("%" + keyword + "%");
            }
        	total = gwcmpKeywordMapper.countByExample(example);
        	if (start != null && limit != null) {
                Page page = new Page(start, limit);
                example.setPage(page);
            }
            list = gwcmpKeywordMapper.selectByExample(example);
        } catch (Exception e) {
            logger.error(logInfo.toString(), e);
            result.put("list", new ArrayList<GwcmpKeyword>(0));
            return result;
        }
        if(list == null) new ArrayList<GwcmpKeyword>(0);
        result.put("list", list);
        result.put("total", total);
	    logger.info("[ getKeywordList: [list = "+list.size()+"]");
        return result;
    }
    
    
    /**
     * 获取关键字任务列表
     * @param start
     * @return
     */
    @RequestMapping(value="/keyword/getKeywordTaskList")
    @ResponseBody
    public Map<String, Object> getKeywordTaskList(
			@RequestParam(value = "start", required = true) Integer start,
            @RequestParam(value = "limit", required = true) Integer limit,
            HttpServletRequest request, HttpServletResponse response) {
        
        // 返回结果
        Map<String, Object> result = new HashMap<String, Object>();
        String operator = GwcmpAdminUtil.getLoginUserName(request);
        StringBuffer logInfo = new StringBuffer();
		logInfo.append("KeywordAct >>>>>").append(" operator:").append(operator)
			.append(" url: /keyword/getKeywordTaskList.do").append(" params: [")
			.append("start=").append(start).append("] ");    
		logger.info(logInfo.toString());
		List<GwcmpProcessTask> list = null;
		Integer total = 0;
        try {
        	GwcmpProcessTaskExample example = new GwcmpProcessTaskExample();
        	example.setOrderByClause("OPERATE_TIME DESC");
        	GwcmpProcessTaskExample.Criteria criteria = example.createCriteria();
        	criteria.andTaskTypeEqualTo(Constants.TASKTYPE_KEYWORD);
        	total = gwcmpProcessTaskMapper.countByExample(example);
        	if (start != null && limit != null) {
                Page page = new Page(start, limit);
                example.setPage(page);
            }
            list = gwcmpProcessTaskMapper.selectByExample(example);
        } catch (Exception e) {
            logger.error(logInfo.toString(), e);
            result.put("list", new ArrayList<GwcmpProcessTask>(0));
            return result;
        }
        if(list == null) new ArrayList<GwcmpProcessTask>(0);
        result.put("list", list);
        result.put("total", total);
	    logger.info("[ getKeywordTaskList: [list = "+list.size()+"]");
        return result;
    }
    
    /**
     * 新增/删除 关键字
     * @param keyWord
     * @return
     */
    @RequestMapping(value="/keyword/saveKeyword")
    @ResponseBody
    public Map<String, Object> saveKeyword(
			@RequestParam(value = "keywordItem", required = true) String keyword,
			@RequestParam(value = "operateType", required = true) String operateType,
            HttpServletRequest request, HttpServletResponse response) {
        
        // 返回结果
        Map<String, Object> result = new HashMap<String, Object>();
        String operator = GwcmpAdminUtil.getLoginUserName(request);
        StringBuffer logInfo = new StringBuffer();
		logInfo.append("KeywordAct >>>>>").append(" operator:").append(operator)
			.append(" url: /keyword/saveKeyword.do").append(" params: [")
			.append("keyWord=").append(keyword).append("operateType=").append(operateType).append("] ");    
		logger.info(logInfo.toString());
        try {
        	//判断是否已存在此关键字
        	GwcmpKeywordExample example = new GwcmpKeywordExample();
        	GwcmpKeywordExample.Criteria criteria = example.createCriteria();
            criteria.andKeywordEqualTo(keyword);
        	List<GwcmpKeyword> list = gwcmpKeywordMapper.selectByExample(example);
        	//获取具体操作 0 新增 1 删除
        	if("1".equals(operateType)){
        		//新增
        		if(list != null && list.size() > 0){
            		result.put("failure", Boolean.TRUE);
                    result.put("msg", "关键字["+keyword+"]已存在！");
                    logger.info("saveKeyword keyWord["+keyword+"] exists!");
                    return result;
            	}else{
            		GwcmpKeyword gwcmpKeyword = new GwcmpKeyword();
            		gwcmpKeyword.setKeyword(keyword);
            		gwcmpKeyword.setLatestOperateTime(new Date());
            		gwcmpKeyword.setLatestOperator(operator);
            		gwcmpKeywordMapper.insertSelective(gwcmpKeyword);
            		//更新GWCMP_TABLE_UPDATE_INFO表
            		updateGwcmpTableUpdateInfo();
            		logger.info("saveKeyword keyWord["+keyword+"] has saved!");
            	}
        	}else if("2".equals(operateType)){
        		//删除
        		if(list != null && list.size() > 0){
        			gwcmpKeywordMapper.deleteByExample(example);
            		//更新GWCMP_TABLE_UPDATE_INFO表
            		updateGwcmpTableUpdateInfo();
                    logger.info("saveKeyword keyWord["+keyword+"] has deleted!");
            	}else{
            		result.put("failure", Boolean.TRUE);
                    result.put("msg", "关键字["+keyword+"]不存在！");
                    logger.info("saveKeyword keyWord["+keyword+"] not exists!");
                    return result;
            	}
        	}
        } catch (Exception e) {
            logger.error(logInfo.toString(), e);
            result.put("failure", Boolean.TRUE);
            result.put("msg", "系统异常");
            return result;
        }
        result.put("success", Boolean.TRUE);
        result.put("msg", "关键字["+keyword+"]已成功更新！");
	    logger.info("[ saveKeyword: result : success ]");
        return result;
    }
    
    /**
     * 批量新增/删除 关键字
     * @param keyWord
     * @return
     */
    @RequestMapping(value="/keyword/batchSaveKeyword")
    @ResponseBody
    public ResponseEntity<String> batchSaveKeyword(
			@RequestParam(value = "keywordFile", required = true) MultipartFile keywordFile,
			@RequestParam(value = "operateType", required = true) String operateType,
			@RequestParam(value = "reason", required = false) String reason,
            HttpServletRequest request, HttpServletResponse response) {
        
        // 返回结果
        Map<String, Object> result = new HashMap<String, Object>();
        HttpHeaders httpHeaders = new HttpHeaders();
        MediaType mediaType = new MediaType("text", "html", Charset.forName("utf-8"));
        httpHeaders.setContentType(mediaType);
        String operator = GwcmpAdminUtil.getLoginUserName(request);
        StringBuffer logInfo = new StringBuffer();
		logInfo.append("KeywordAct >>>>>").append(" operator:").append(operator)
			.append(" url: /keyword/batchSaveKeyword.do").append(" params: [")
			.append("keywordFile=").append(keywordFile.getOriginalFilename()).append(" operateType=").append(operateType).append("] ");    
		logger.info(logInfo.toString());
        try {
        	//把文件上传到指定路径
        	if (keywordFile == null || keywordFile.getSize() == 0) {
				result.put("failure", Boolean.valueOf(true));
				result.put("msg", "文件内容为空！");
				return new ResponseEntity<String>(Json.toJson(result), httpHeaders, HttpStatus.OK);
			}
        	String filePath = resourceManager.getValue("keyword.upload.path")+new SimpleDateFormat("yyyy-MM-dd").format(new Date())+File.separator;
        	File storeDir = new File(filePath);
        	if(!storeDir.exists()){
        		storeDir.mkdir();
        	}
        	String taskId = UUID.randomUUID().toString();
        	String fileName =  taskId + keywordFile.getOriginalFilename().substring(
							keywordFile.getOriginalFilename().lastIndexOf(
									"."));
        	File uploadFile = new File(filePath,fileName);
        	logger.info("batchSaveKeyword file store:"+filePath+fileName);
        	keywordFile.transferTo(uploadFile);
        	//更新任务表
        	GwcmpProcessTask gwcmpProcessTask = new GwcmpProcessTask();
        	gwcmpProcessTask.setFilePath(filePath + fileName);
        	gwcmpProcessTask.setId(taskId);
        	gwcmpProcessTask.setOperator(operator);
        	gwcmpProcessTask.setTaskType(Constants.TASKTYPE_KEYWORD);
        	gwcmpProcessTask.setOperateTime(new Date());
        	gwcmpProcessTask.setOperateType(Short.valueOf(operateType));
        	gwcmpProcessTask.setStatus(Short.valueOf(Constants.uploadStatus.PENDING.ordinal()+""));
        	gwcmpProcessTask.setReason(reason);
        	int uploadFlag = gwcmpProcessTaskMapper.insertSelective(gwcmpProcessTask);
        	if(uploadFlag == 0){
        		result.put("failure", Boolean.TRUE);
                result.put("msg", "创建任务失败！");
                logger.info("[ batchSaveKeyword: result : fail ]");
                return new ResponseEntity<String>(Json.toJson(result), httpHeaders, HttpStatus.OK);
        	}
        } catch (Exception e) {
            logger.error(logInfo.toString(), e);
            result.put("failure", Boolean.TRUE);
            result.put("msg", "系统异常");
            return new ResponseEntity<String>(Json.toJson(result), httpHeaders, HttpStatus.OK);
        }
        result.put("success", Boolean.TRUE);
        result.put("msg", "关键字["+keywordFile.getName()+"]已成功上传！");
	    logger.info("[ batchSaveKeyword: result : success ]");
	    return new ResponseEntity<String>(Json.toJson(result), httpHeaders, HttpStatus.OK);
    }
    
    

    /**
     * 导出关键字列表
     * @param keyWord
     * @return
     */
    @RequestMapping(value="/keyword/exportKeywordList")
    @ResponseBody
    public void exportKeywordList(
            @RequestParam(value = "keyword", required = false) String keyword,
            HttpServletRequest request, HttpServletResponse response) {
        
        // 返回结果
        StringBuffer logInfo = new StringBuffer();
        String operator = GwcmpAdminUtil.getLoginUserName(request);
		logInfo.append("KeywordAct >>>>>").append(" operator:").append(operator)
			.append(" url: /keyword/exportKeywordList.do").append(" params: [")
			.append(",keyWord=").append(keyword).append("] ");    
		logger.info(logInfo.toString());
		List<GwcmpKeyword> list = null;
        try {
        	GwcmpKeywordExample example = new GwcmpKeywordExample();
        	example.setOrderByClause("LATEST_OPERATE_TIME DESC");
        	GwcmpKeywordExample.Criteria criteria = example.createCriteria();
        	if (StringUtils.isNotBlank(keyword)) {
                criteria.andKeywordLike("%" + keyword + "%");
            }
            list = gwcmpKeywordMapper.selectByExample(example);
        } catch (Exception e) {
            logger.error(logInfo.toString(), e);
            return;
        }
        if(list == null) new ArrayList<GwcmpKeyword>(0);
        HSSFWorkbook wb = writeOrderInfo2ExcelOutputStream(list, response);
		String filename = "Keyword_"
				+ new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())
				+ ".xls";
		downloadExcel(wb, filename, response);
    }
    
    
    private void updateGwcmpTableUpdateInfo(){
    	GwcmpTableUpdateInfo updateInfo = new GwcmpTableUpdateInfo();
    	GwcmpTableUpdateInfoExample example = new GwcmpTableUpdateInfoExample();
    	GwcmpTableUpdateInfoExample.Criteria criteria = example.createCriteria();
    	criteria.andTableNameEqualTo("GWCMP_KEYWORD");
    	List<GwcmpTableUpdateInfo> list = gwcmpTableUpdateInfoMapper.selectByExample(example);
    	if(list != null && list.size() > 0){
    		//更新GwcmpTableUpdateInfo表
    		updateInfo = list.get(0);
    		updateInfo.setUpdateTime(new Date());
    		gwcmpTableUpdateInfoMapper.updateByPrimaryKey(updateInfo);
    		logger.info("updateGwcmpTableUpdateInfo GWCMP_KEYWORD update!");
    	} else {
    		//插入数据
    		updateInfo.setTableName("GWCMP_KEYWORD");
    		updateInfo.setUpdateTime(new Date());
    		gwcmpTableUpdateInfoMapper.insertSelective(updateInfo);
    		logger.info("updateGwcmpTableUpdateInfo GWCMP_KEYWORD insert!");
    	}
    }
    
    
    
 // 创建工作量excel文件
 	private HSSFWorkbook writeOrderInfo2ExcelOutputStream(
 			List<GwcmpKeyword> list, HttpServletResponse response) {
 		/**
 		 * List<Map<String, Object>>
 		 */
 		HSSFWorkbook wb = new HSSFWorkbook();
 		HSSFCellStyle numStyle = wb.createCellStyle();
 		numStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat("0"));
 		int size = list == null ? 0 : list.size();
 		if (size > 0) {
 			int sheetSize = 5000;
 			int sheetCount = (int) Math.ceil(size / sheetSize + 1);
 			
 			for (int n = 0; n < sheetCount; n++) {
 				HSSFSheet sheet = wb.createSheet("表" + (n + 1));
 				sheet.setDefaultColumnWidth((short) 10);
 				HSSFRow rowHead = sheet.createRow(0);

 				rowHead.createCell((short) 0).setCellValue(
 						new HSSFRichTextString("关键字内容"));
 				rowHead.createCell((short) 1).setCellValue(
 						new HSSFRichTextString("最近操作账号"));
 				rowHead.createCell((short) 2).setCellValue(
 						new HSSFRichTextString("最近操作时间"));

 				// 10001: 0-4999, 5000-9999, 10000-10001
 				for (int i = n * sheetSize; i < list.size()
 						&& i < (n + 1) * sheetSize; i++) {
 					HSSFRow rowBody = sheet.createRow(i % sheetSize + 1);
 					GwcmpKeyword keyWords = list.get(i);
 					rowBody.createCell((short) 0).setCellValue(
 							new HSSFRichTextString(getNullString(getNullString(keyWords.getKeyword()))));
					rowBody.createCell((short) 1).setCellValue(
 							new HSSFRichTextString(getNullString(getNullString(keyWords.getLatestOperator()))));
					rowBody.createCell((short) 2).setCellValue(
 							new HSSFRichTextString(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(keyWords.getLatestOperateTime())));
 				}
 			}
 		}
 		return wb;
 	}
 	
	/**
	 * @param wb
	 * @param filename
	 * @param response
	 */
	private void downloadExcel(HSSFWorkbook wb, String filename,
			HttpServletResponse response) {

		ServletOutputStream out = null;
		try {
			out = response.getOutputStream();
			response.setHeader("Content-Type", "application/force-download");
			response.setHeader("Content-Disposition", "attachment;filename="
					+ URLEncoder.encode(filename, "UTF-8"));
			wb.write(out);
			out.close();
		} catch (Exception e) {
			logger.error(">>>>>fail to write output stream", e);
		} finally {
			if (out != null) {
				try {
					out.close();
				} catch (IOException e) {
					logger.error(">>>>>fail to close output stream", e);
				}
			}
		}
	}
	
	private String getNullString(Object data){
		if(data == null){
			return "";
		}
		String dataStr = String.valueOf(data);
		if("null".equalsIgnoreCase(dataStr)){
			return "";
		}
		return dataStr;
	}
}
